import { observe } from ".";

/** 1. 拦截数组成员*/
// {arr:[{a:1}]}
export function observerArray(inserted){ // 要循环数组一次对数组中没一项进行观测
    for(let i = 0 ; i < inserted.length;i++){
        observe(inserted[i]); // 只会对 对象成员 和 数组方法进行观测
    }
}

/** 2. 拦截数组方法
    + 如果数组方法导致新增数组成员,也需要对这些新增数组成员进行观察*/
// 主要要做的事就是拦截用户调用的push shift unshift pop reverse sort splice(这些会改变原数组的数组方法),而像concat这些不会改变原数组的不需要拦截
const oldArrayProtoMethods = Array.prototype;

// 拷贝的一个新的对象 可以查找到 老的方法
export let arrayMethods = Object.create(oldArrayProtoMethods);

const methods = [
    'push',
    'shift',
    'pop',
    'unshift',
    'reverse',
    'sort',
    'splice'
];

methods.forEach(method=>{   // arr.push(1,2,3)  args=[1,2,3]
    arrayMethods[method] = function (...args) { // 函数劫持  切片编程
        // call apply bind的用法
        let r = oldArrayProtoMethods[method].apply(this,args);
        // todo
        let inserted;
        switch (method) { // 只对 新增的属性 再次进行观察 其他方法没有新增属性
            case 'push':
            case 'unshift':
                inserted = args;
                break;
            case 'splice':
                inserted = args.slice(2);  // 获取splice 新增的内容
            default:
                break;
        }
        if(inserted) observerArray(inserted); /** 如果数组的方法会新增成员,那么也需要对这些成员进行观察*/
        console.log('调用了数组更新的方法了  -- 更新视图');
        this.__ob__.dep.notify(); // 通知视图更新
        return r;
    }
})
